TC-3753 advisory’s query and pruning functionality#2288
Merged
bxf12315 merged 2 commits intoguacsec:mainfrom Mar 17, 2026
Merged
TC-3753 advisory’s query and pruning functionality#2288bxf12315 merged 2 commits intoguacsec:mainfrom
bxf12315 merged 2 commits intoguacsec:mainfrom
Conversation
Contributor
Reviewer's GuideThis PR introduces shared list/prune/delete utilities in a new common module, refactors the SBOM API and commands to use these shared types and helpers, and adds new advisory API and CLI commands (list and prune) that reuse the same infrastructure, along with documentation updates for the new advisory functionality. Sequence diagram for advisory prune command flowsequenceDiagram
actor User
participant CliMain as main_rs
participant Commands as Commands
participant AdvCmd as AdvisoryCommands
participant AdvApi as advisory_api
participant Common as common_module
participant Client as ApiClient
User->>CliMain: invoke trustify advisory prune ...
CliMain->>Commands: parse args to Advisory command
Commands->>AdvCmd: run(ctx)
AdvCmd->>AdvCmd: build PruneParams
AdvCmd->>AdvApi: prune(&ctx.client, ¶ms)
AdvApi->>Common: build_prune_query(¶ms)
Common-->>AdvApi: (query, ListParams)
AdvApi->>AdvApi: log prune query
AdvApi->>Client: get_with_query("/v2/advisory", &ListParams)
Client-->>AdvApi: JSON response
AdvApi->>AdvApi: parse JSON, build Vec<DeleteEntry>
alt params.dry_run == true
AdvApi->>Common: new_delete_result(total)
Common-->>AdvApi: DeleteResult
else params.dry_run == false
AdvApi->>Common: delete_entries(&client, "/v2/advisory", entries, params.concurrency)
Common->>Client: delete("/v2/advisory/{id}") for each entry
Client-->>Common: delete result per entry
Common-->>AdvApi: aggregated DeleteResult
end
AdvApi-->>AdvCmd: DeleteResult
AdvCmd->>AdvCmd: print summary, write optional output file
AdvCmd-->>Commands: ExitCode::SUCCESS
Commands-->>CliMain: ExitCode::SUCCESS
CliMain-->>User: command completed
Class diagram for shared common deletion utilities and consumersclassDiagram
class ListParams {
+Option~String~ q
+Option~u32~ limit
+Option~u32~ offset
+Option~String~ sort
}
class PruneParams {
+Option~String~ q
+Option~u32~ limit
+Option~DateTime_Local~ published_before
+Option~i64~ older_than
+Option~Vec~String~~ label
+Option~u32~ keep_latest
+bool dry_run
+usize concurrency
}
class DeleteEntry {
+String id
+String identifier
}
class DeleteResult {
+Vec~DeletedResult~ deleted
+u32 deleted_total
+Vec~SkippedResult~ skipped
+u32 skipped_total
+Vec~FailedResult~ failed
+u32 failed_total
+u32 total
}
class DeletedResult {
+String id
+String identifier
}
class SkippedResult {
+String id
+String identifier
}
class FailedResult {
+String id
+String identifier
+String error
}
class CommonModule {
+build_prune_query(params PruneParams) (String, ListParams)
+delete_entries(client ApiClient, base_path String, entries Vec~DeleteEntry~, concurrency usize) DeleteResult
+new_delete_result(total u32) DeleteResult
}
class ApiClient {
+get_with_query(path String, params ListParams) String
+delete(path String) Result
}
class SbomApi {
+prune(client ApiClient, params PruneParams) DeleteResult
+delete_list(client ApiClient, entries Vec~DeleteEntry~, concurrency usize) DeleteResult
+delete_by_query(client ApiClient, query String, concurrency usize, dry_run bool) DeleteResult
}
class AdvisoryApi {
+list(client ApiClient, params ListParams) String
+prune(client ApiClient, params PruneParams) DeleteResult
}
class SbomCommands {
+run(ctx Context) ExitCode
}
class AdvisoryCommands {
+run(ctx Context) ExitCode
}
class Commands {
+Sbom command
+Advisory command
+Auth command
+run(ctx Context) ExitCode
}
CommonModule "1" -- "many" ListParams : uses
CommonModule "1" -- "many" PruneParams : uses
CommonModule "1" -- "many" DeleteEntry : uses
CommonModule "1" -- "many" DeleteResult : creates
DeleteResult "1" o-- "many" DeletedResult
DeleteResult "1" o-- "many" SkippedResult
DeleteResult "1" o-- "many" FailedResult
SbomApi ..> CommonModule : uses
AdvisoryApi ..> CommonModule : uses
SbomCommands ..> SbomApi : calls
AdvisoryCommands ..> AdvisoryApi : calls
Commands ..> SbomCommands : dispatches
Commands ..> AdvisoryCommands : dispatches
Commands ..> ApiClient : holds in Context
ApiClient <.. CommonModule : passed_in
ApiClient <.. SbomApi : passed_in
ApiClient <.. AdvisoryApi : passed_in
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Contributor
Author
|
@ruromero In order to implement operations related to advisories, I refactored the existing code. Please review them. |
ruromero
approved these changes
Mar 16, 2026
Contributor
ruromero
left a comment
There was a problem hiding this comment.
The functional changes look good to me and seems a reasonable refactoring
d57c27a to
722c262
Compare
Contributor
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- In
AdvisoryCommands::Prune, the dry-run summary usesprune_result.deleted_total, butnew_delete_resultalways sets this to 0 for dry runs; you probably want to reportprune_result.totalinstead so the preview reflects how many advisories would be deleted. - The
outputargument forAdvisoryCommands::Prunehas adefault_value = "advisories.json", which means a results file is always written even when the flag is not specified; if you want output to be truly optional, drop the default and treatNoneas “don’t write a file.”
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `AdvisoryCommands::Prune`, the dry-run summary uses `prune_result.deleted_total`, but `new_delete_result` always sets this to 0 for dry runs; you probably want to report `prune_result.total` instead so the preview reflects how many advisories would be deleted.
- The `output` argument for `AdvisoryCommands::Prune` has a `default_value = "advisories.json"`, which means a results file is always written even when the flag is not specified; if you want output to be truly optional, drop the default and treat `None` as “don’t write a file.”
## Individual Comments
### Comment 1
<location path="etc/trustify-cli/src/commands/advisory.rs" line_range="147-151" />
<code_context>
+
+ let prune_result = advisory_api::prune(&ctx.client, ¶ms).await?;
+
+ if !quiet {
+ if *dry_run {
+ println!(
+ "[DRY-RUN] Would delete {} advisory(s)",
+ prune_result.deleted_total
+ );
+ } else {
</code_context>
<issue_to_address>
**issue (bug_risk):** Dry-run summary prints `deleted_total` instead of the number of advisories that would be deleted
In dry-run mode `prune_result` comes from `new_delete_result(total)`, so `deleted_total` is always 0 while `total` is the number of candidates. Using `deleted_total` here will always print 0; this should instead use `prune_result.total` (or the underlying `total`) to show how many advisories would be deleted.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
722c262 to
aab546b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary by Sourcery
Add advisory management support to the CLI and centralize shared query/pruning and deletion logic for SBOMs and advisories.
New Features:
Enhancements: